﻿using BCAMap.AMap;
using BCAMap.Dto;
using BCCommon;
using BCCommon.Extensions;
using BCCommon.TMS.Order;
using BCCommon.TMS.Transport;
using BCData.TMS.Order.Order;
using BCData.TMS.Order.OrderExtention;
using BCData.TMS.Order.OrderMoveHouseSpecificationServiceRecord;
using BCData.TMS.Order.OrderPool;
using BCData.TMS.Order.OrderSpecificServiceRecord;
using BCData.TMS.OrderFreightFormulaRecord;
using BCData.TMS.OrderFreightRecord;
using BCDto.TMS.InsuredConfig;
using BCDto.TMS.MarketingCoupon.MarketingCoupon;
using BCDto.TMS.NightFreightConfiguration;
using BCDto.TMS.Order;
using BCDto.TMS.Order.Order;
using BCDto.TMS.OrderFreightAppendRecord;
using BCDto.TMS.TransportOrder;
using BCDto.Website.User;
using BCEntity.Common.Area;
using BCEntity.TMS.Order.Order;
using BCEntity.TMS.Order.OrderExtention;
using BCEntity.TMS.Order.OrderMoveHouseSpecificationServiceRecord;
using BCEntity.TMS.Order.OrderPool;
using BCEntity.TMS.OrderFreightFormulaRecord;
using BCEntity.TMS.OrderFreightRecord;
using BCEntity.TMS.OrderSpecificServiceRecord;
using BCService.Common.Area;
using BCService.Sim.Company.Company;
using BCService.TMS.Agent.AgentAreaRecord;
using BCService.TMS.Agent.AgentRecord;
using BCService.TMS.FreightConfigurationService;
using BCService.TMS.InsuredConfig;
using BCService.TMS.MarketingCoupon.MarketingCoupon;
using BCService.TMS.MarketingCoupon.MarketingCouponReceive;
using BCService.TMS.MarketingCoupon.MarketingCouponUsing;
using BCService.TMS.MoveHouseConfig.MoveHouseSpecificationServiceConfig;
using BCService.TMS.NightFreightConfiguration;
using BCService.TMS.OrderFreightFormulaRecord;
using BCService.TMS.TransportOrder;
using BCService.TMS.TransportSpecificServiceConfig;
using BCService.TMS.TransportSpecificServiceConfigOverWrite;
using BCService.TMS.VehicleBusinessMappingOverwrite;
using BCService.TMS.VehicleSuiteBusinessConfig;
using BCService.TMS.VehicleTransportBusinessConfig;
using BCService.TMS.VehicleTypeService;
using BCService.TMS.WorryFreeMoveSuiteConfig;
using BCService.Utils;
using Microsoft.Extensions.Configuration;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BCService.TMS.Order.Order
{
    /// <summary>
    /// 无忧搬家订单
    /// </summary>
    public class WorryFreeMoveSuiteOrderService : IOrderService
    {
        private readonly IDatabaseContext databaseContext;
        private readonly IConfiguration configuration;
        private readonly IZoneService zoneService;
        private readonly IAMapUtils aMapUtils;
        private readonly ICompanyService companyService;
        private readonly IAgentRecordService agentRecordService;
        private readonly IAgentAreaRecordService agentAreaRecordService;
        private readonly ITransportOrderService transportOrderService;
        private readonly IVehicleTransportBusinessConfigService vehicleTransportBusinessConfigService;
        private readonly IVehicleBusinessMappingOverwriteService vehicleBusinessMappingOverwriteService;
        private readonly IMarketingCouponService marketingCouponService;
        private readonly IMarketingCouponReceiveService marketingCouponReceiveService;
        private readonly IMarketingCouponUsingService marketingCouponUsingService;
        private readonly IVehicleTypeService vehicleTypeService;
        private readonly IVehicleSuiteBusinessConfigService vehicleSuiteBusinessConfigService;
        private readonly IWorryFreeMoveSuiteConfigService worryFreeMoveSuiteConfigService;
        private readonly IFreightConfigurationService freightConfigurationService;
        private readonly INightFreightConfigurationService nightFreightConfigurationService;
        private readonly IMoveHouseSpecificationServiceConfigService moveHouseSpecificationServiceConfigService;
        private readonly IMoveHouseSpecificationServiceConfigOverWriteService moveHouseSpecificationServiceConfigOverWriteService;
        private readonly IInsuredConfigService insuredConfigService;
        private readonly IOrderData orderData;
        private readonly IOrderExtentionData orderExtentionData;
        private readonly IOrderMoveHouseSpecificationServiceRecordData orderMoveHouseSpecificationServiceRecordData;
        private readonly IOrderSpecificServiceRecordData orderSpecificServiceRecordData;
        private readonly IOrderPoolData orderPoolData;
        private readonly IOrderFreightRecordData orderFreightRecordData;
        private readonly IOrderFreightFormulaRecordData orderFreightFormulaRecordData; 
        private readonly ITransportSpecificServiceConfigOverWriteService transportSpecificServiceConfigOverWriteService;
        private readonly ITransportSpecificServiceConfigService transportSpecificServiceConfigService;
        public WorryFreeMoveSuiteOrderService(IDatabaseContext databaseContext,
            IConfiguration configuration,
            IZoneService zoneService,
            IAMapUtils aMapUtils,
            ICompanyService companyService,
            IAgentRecordService agentRecordService,
            IAgentAreaRecordService agentAreaRecordService,
            ITransportOrderService transportOrderService,
            IVehicleTransportBusinessConfigService vehicleTransportBusinessConfigService,
            IVehicleBusinessMappingOverwriteService vehicleBusinessMappingOverwriteService,
            IMarketingCouponService marketingCouponService,
            IMarketingCouponReceiveService marketingCouponReceiveService,
            IMarketingCouponUsingService marketingCouponUsingService,
            IVehicleTypeService vehicleTypeService,
            IVehicleSuiteBusinessConfigService vehicleSuiteBusinessConfigService,
            IWorryFreeMoveSuiteConfigService worryFreeMoveSuiteConfigService,
            IFreightConfigurationService freightConfigurationService,
            INightFreightConfigurationService nightFreightConfigurationService,
            IMoveHouseSpecificationServiceConfigService moveHouseSpecificationServiceConfigService,
            IMoveHouseSpecificationServiceConfigOverWriteService moveHouseSpecificationServiceConfigOverWriteService,
            IInsuredConfigService insuredConfigService,
            IOrderData orderData,
            IOrderExtentionData orderExtentionData,
            IOrderMoveHouseSpecificationServiceRecordData orderMoveHouseSpecificationServiceRecordData,
            IOrderSpecificServiceRecordData orderSpecificServiceRecordData,
            IOrderPoolData orderPoolData,
            IOrderFreightRecordData orderFreightRecordData,
            IOrderFreightFormulaRecordData orderFreightFormulaRecordData,
            ITransportSpecificServiceConfigOverWriteService transportSpecificServiceConfigOverWriteService,
            ITransportSpecificServiceConfigService transportSpecificServiceConfigService)
        {
            this.databaseContext = databaseContext;
            this.configuration = configuration;
            this.zoneService = zoneService;
            this.aMapUtils = aMapUtils;
            this.companyService = companyService;
            this.agentRecordService = agentRecordService;
            this.agentAreaRecordService = agentAreaRecordService;
            this.transportOrderService = transportOrderService;
            this.vehicleTransportBusinessConfigService = vehicleTransportBusinessConfigService;
            this.vehicleBusinessMappingOverwriteService = vehicleBusinessMappingOverwriteService;
            this.marketingCouponService = marketingCouponService;
            this.marketingCouponReceiveService = marketingCouponReceiveService;
            this.marketingCouponUsingService = marketingCouponUsingService;
            this.vehicleTypeService = vehicleTypeService;
            this.vehicleSuiteBusinessConfigService = vehicleSuiteBusinessConfigService;
            this.worryFreeMoveSuiteConfigService = worryFreeMoveSuiteConfigService;
            this.freightConfigurationService = freightConfigurationService;
            this.nightFreightConfigurationService = nightFreightConfigurationService;
            this.moveHouseSpecificationServiceConfigService = moveHouseSpecificationServiceConfigService;
            this.moveHouseSpecificationServiceConfigOverWriteService = moveHouseSpecificationServiceConfigOverWriteService;
            this.orderData = orderData;
            this.orderExtentionData = orderExtentionData;
            this.orderMoveHouseSpecificationServiceRecordData = orderMoveHouseSpecificationServiceRecordData;
            this.orderSpecificServiceRecordData = orderSpecificServiceRecordData;
            this.orderPoolData = orderPoolData;
            this.orderFreightRecordData = orderFreightRecordData;
            this.orderFreightFormulaRecordData = orderFreightFormulaRecordData;
            this.transportSpecificServiceConfigOverWriteService = transportSpecificServiceConfigOverWriteService;
            this.transportSpecificServiceConfigService = transportSpecificServiceConfigService;
            this.insuredConfigService = insuredConfigService;
        }

        #region 计算运费
        public List<OrderCostChecklistDto> CalculateShippingCost(long? userId,OrderShippingCostRequestDto requestDto)
        {
            return GetShippingCost(requestDto, userId, false, out OrderEntity entity, out List<OrderMoveHouseSpecificationServiceRecordEntity> outEntities, out List<OrderSpecificServiceRecordEntity> outSpecificEntities);
        }

        private List<OrderCostChecklistDto> GetShippingCost(OrderShippingCostRequestDto requestDto, long? userId, bool createOrder, out OrderEntity entity, out List<OrderMoveHouseSpecificationServiceRecordEntity> outEntities, out List<OrderSpecificServiceRecordEntity> outSpecificEntities)
        {
            if (string.IsNullOrWhiteSpace(requestDto.CountyCode))
            {
                throw new ArgumentException("出发区县不能为空!");
            }
            if (requestDto.IsBook && !requestDto.BookTime.HasValue)
            {
                throw new ArgumentException("请选择预约时间!");
            }
            if (!requestDto.ConsigneeAddress.Any())
            {
                throw new ArgumentException("目的地不能为空!");
            }
            if (requestDto.ConsigneeAddress.Any(p => string.IsNullOrWhiteSpace(p.EndCountyCode)))
            {
                throw new ArgumentException("目的地城市不能为空!");
            }
            if (!requestDto.VehicleTypeId.HasValue || requestDto.VehicleTypeId.Value == 0)
            {
                throw new ArgumentException("请选择正确的车型!");
            }
            if (!requestDto.VehicleCategoryReferenceId.HasValue)
            {
                throw new ArgumentException("此套餐车辆分类Id不可为空!");
            }
            if (!requestDto.WorryFreeMoveSuiteConfigId.HasValue)
            {
                throw new ArgumentException("请选择一个套餐!");
            }
            if (requestDto.IsInsuredPrice && !requestDto.InsuredConfigId.HasValue)
            {
                throw new ArgumentException("有保价服务时，保价配置Id不允许为空!");
            }
            if (requestDto.IsInsuredPrice && (!requestDto.InsuredPrice.HasValue || requestDto.InsuredPrice.Value == 0))
            {
                throw new ArgumentException("有保价服务时，保价金额应大于0元!");
            }

            MarketingCouponDto marketingCouponDto = null;
            if (requestDto.CouponId.HasValue)
            {
                marketingCouponDto = this.marketingCouponService.GetSingle(requestDto.CouponId.Value);
                if (marketingCouponDto == null)
                {
                    throw new ArgumentException("优惠券信息不正确!");
                }
                if (this.marketingCouponUsingService.Exists(requestDto.CouponId.Value))
                {
                    throw new ArgumentException("此优惠券已使用过，无法重复使用!");
                }
            }

            var agentAreaRecordDto = this.agentAreaRecordService.GetLastLevelByCode(requestDto.CountyCode);
            if (agentAreaRecordDto == null)
            {
                throw new ArgumentException("发货区域相关业务正在筹划中，敬请期待!");
            }
            var transportBusinessConfigViewDto = this.vehicleTransportBusinessConfigService.GetList(agentAreaRecordDto.AgentAreaRecordId, requestDto.CountyCode);
            if (!transportBusinessConfigViewDto.Any(p => p.TransportBusiness == TransportBusinessType.Moving))
            {
                throw new ArgumentException("此业务正在筹划中，敬请期待!");
            }
            var suiteBusinessConfigList = this.vehicleSuiteBusinessConfigService.GetList(agentAreaRecordDto.AgentRecordId);
            if (!suiteBusinessConfigList.Any(p => p.SuiteBusinessType == VehicleSuiteBusinessType.WorryFreeMove && p.Enabled))
            {
                throw new ArgumentException("此区域并未开启无忧搬家套餐!");
            }
            if (!suiteBusinessConfigList.Any(p => p.SuiteBusinessType == VehicleSuiteBusinessType.WorryFreeMove && p.Enabled && p.CountyCode == requestDto.CountyCode))
            {
                throw new ArgumentException("此区域未启用无忧搬家套餐!");
            }
            var suiteConfig = worryFreeMoveSuiteConfigService.Get(requestDto.WorryFreeMoveSuiteConfigId.Value);
            if (suiteConfig == null)
            {
                throw new ArgumentException("此套餐不存在!");
            }
            var vehicleBusinessMappingOverwriteDto = vehicleBusinessMappingOverwriteService.Get(suiteConfig.VehicleBusinessMappingId, agentAreaRecordDto.AgentRecordId);
            if (vehicleBusinessMappingOverwriteDto == null)
            {
                throw new ArgumentException("此车型业务配置不正确!");
            }
            var zoneEntity = this.zoneService.GetFromZoneEntity(requestDto.CountyCode);
            if (zoneEntity == null || zoneEntity.provinceEntity == null || zoneEntity.cityEntity == null || zoneEntity.countyEntity == null)
            {
                throw new ArgumentException("此区域信息不正确!");
            }

            var freightConfiguration = this.freightConfigurationService.Get(suiteConfig.VehicleTypeId, vehicleBusinessMappingOverwriteDto.VehicleCategoryReferenceId.Value, zoneEntity.provinceEntity.ProvinceCode, zoneEntity.cityEntity.CityCode, zoneEntity.countyEntity.CountyCode, requestDto.SourceType, requestDto.FreightType);
            if (freightConfiguration == null)
            {
                throw new Exception("此区域缺少运费信息!");
            }

            #region 计算距离
            int distanceTotal = 0;
            foreach (var item in requestDto.ConsigneeAddress)
            {
                var endZoneEntity = this.zoneService.GetFromZoneEntity(item.EndCountyCode);
                if (endZoneEntity == null || endZoneEntity.provinceEntity == null || endZoneEntity.cityEntity == null || endZoneEntity.countyEntity == null)
                {
                    throw new ArgumentException("目的地区域信息不正确!");
                }
                var directionResponseDto = this.aMapUtils.GetDirectionDriving(new DirectionDrivingRequestDto
                {
                    Origin = new double[2] { requestDto.Longitude, requestDto.Latitude },
                    Destination = new double[2] { item.EndLongitude, item.EndLatitude }
                });
                int distance = 0;
                foreach (var path in directionResponseDto.Route.Paths)
                {
                    int len = 0;
                    if (int.TryParse(path.distance, out len))
                    {
                        distance += len;
                    }
                }
                distanceTotal += distance;
                //if (endZoneEntity.cityEntity.CityCode != zoneEntity.cityEntity.CityCode&&distance/1000>200)
                //{
                //    throw new ArgumentException("非同一城市")
                //}

            }
            if (distanceTotal > 0)
            {
                distanceTotal = distanceTotal % 1000 > 0 ? distanceTotal / 1000 + 1 : distanceTotal / 1000;
            }
            #endregion

            #region 夜间服务费配置获取及计算
            DateTime today = requestDto.IsBook ? requestDto.BookTime.Value : DateTime.Now;

            var nightFreightConfigurationDtos = this.nightFreightConfigurationService.GetList(agentAreaRecordDto.AgentRecordId);

            NightFreightConfigurationViewDto nightFreightConfigurationDto = null;

            bool isNight = false;
            if (nightFreightConfigurationDtos.Any())
            {
                if (nightFreightConfigurationDtos.Any(p => today.Hour > p.StartHour && today.Hour < p.EndHour))
                {
                    isNight = true;
                    nightFreightConfigurationDto = nightFreightConfigurationDtos.First(p => today.Hour >= p.StartHour && today.Hour < p.EndHour);
                }
                else if (nightFreightConfigurationDtos.Any(p => today.Hour == p.StartHour && today.Minute >= p.StartMinute))
                {
                    isNight = true;
                    nightFreightConfigurationDto = nightFreightConfigurationDtos.First(p => today.Hour == p.StartHour && today.Minute >= p.StartMinute);
                }
                else if (nightFreightConfigurationDtos.Any(p => today.Hour > p.StartHour && today.Hour == p.EndHour && today.Minute <= p.EndMinute))
                {
                    isNight = true;
                    nightFreightConfigurationDto = nightFreightConfigurationDtos.First(p => today.Hour > p.StartHour && today.Hour == p.EndHour && today.Minute <= p.EndMinute);
                }
            }
            #endregion

            #region 搬家额外服务
            OrderCostChecklistDto moveSpecificServiceCost = new OrderCostChecklistDto();
            moveSpecificServiceCost.CostCode = OrderCostType.MoveSpecificServiceAmount.ToString();
            moveSpecificServiceCost.CostTitle = OrderCostType.MoveSpecificServiceAmount.GetDescriptionString(); //搬家特殊服务费
            moveSpecificServiceCost.Checklist = new List<OrderCostChecklistDto>();
            decimal specificServiceAmount = 0;
            int specificServiceCount = 0;
            #region 计算额外服务费
            outEntities = new List<OrderMoveHouseSpecificationServiceRecordEntity>();
            if (requestDto.MoveSpecificationServices != null && requestDto.MoveSpecificationServices.Any())
            {
                foreach (var specificService in requestDto.MoveSpecificationServices)
                {
                    if (specificService.MoveHouseSpecificationServiceConfigOverWriteId.HasValue && specificService.MoveHouseSpecificationServiceConfigOverWriteId.Value > 0)
                    {
                        var specificServiceDto = this.moveHouseSpecificationServiceConfigOverWriteService.GetById(specificService.MoveHouseSpecificationServiceConfigOverWriteId.Value);
                        if (specificServiceDto != null)
                        {
                            decimal servicePrice = (specificServiceDto.Price.Value * specificService.Number);
                            specificServiceCount += specificService.Number;
                            specificServiceAmount += servicePrice;
                            OrderCostChecklistDto moveSpecificServiceCostItem = new OrderCostChecklistDto();
                            moveSpecificServiceCostItem.CostCode = OrderCostType.MoveSpecificServiceChildAmount.ToString();
                            moveSpecificServiceCostItem.CostTitle = specificServiceDto.SpecificationServiceName;
                            moveSpecificServiceCostItem.CostValue = servicePrice;
                            moveSpecificServiceCostItem.ParentCostCode = moveSpecificServiceCost.CostCode;
                            moveSpecificServiceCost.Checklist.Add(moveSpecificServiceCostItem);
                            if (createOrder)
                            {
                                OrderMoveHouseSpecificationServiceRecordEntity outEntity = new OrderMoveHouseSpecificationServiceRecordEntity();
                                outEntity.MoveHouseSpecificationServiceConfigId = specificService.MoveHouseSpecificationServiceConfigId;
                                outEntity.MoveHouseConfigId = specificServiceDto.MoveHouseConfigId;
                                outEntity.MoveHouseSpecificationConfigId = specificServiceDto.MoveHouseSpecificationConfigId;
                                outEntity.SpecificationName = specificServiceDto.SpecificationName;
                                outEntity.SpecificationServiceConfigId = specificServiceDto.SpecificationServiceConfigId;
                                outEntity.SpecificationServiceName = specificServiceDto.SpecificationServiceName;
                                outEntity.Price = specificServiceDto.Price;
                                outEntities.Add(outEntity);
                            }
                        }
                    }
                    else
                    {
                        var specificServiceDto = this.moveHouseSpecificationServiceConfigService.GetById(specificService.MoveHouseSpecificationServiceConfigId);
                        if (specificServiceDto != null)
                        {
                            decimal servicePrice = (specificServiceDto.Price.Value * specificService.Number);
                            specificServiceCount += specificService.Number;
                            specificServiceAmount += servicePrice;
                            OrderCostChecklistDto moveSpecificServiceCostItem = new OrderCostChecklistDto();
                            moveSpecificServiceCostItem.CostCode = OrderCostType.MoveSpecificServiceChildAmount.ToString();
                            moveSpecificServiceCostItem.CostTitle = specificServiceDto.SpecificationServiceName;
                            moveSpecificServiceCostItem.CostValue = servicePrice;
                            moveSpecificServiceCostItem.ParentCostCode = moveSpecificServiceCost.CostCode;
                            moveSpecificServiceCost.Checklist.Add(moveSpecificServiceCostItem);
                            if (createOrder)
                            {
                                OrderMoveHouseSpecificationServiceRecordEntity outEntity = new OrderMoveHouseSpecificationServiceRecordEntity();
                                outEntity.MoveHouseSpecificationServiceConfigId = specificService.MoveHouseSpecificationServiceConfigId;
                                outEntity.MoveHouseConfigId = specificServiceDto.MoveHouseConfigId;
                                outEntity.MoveHouseSpecificationConfigId = specificServiceDto.MoveHouseSpecificationConfigId;
                                outEntity.SpecificationName = specificServiceDto.SpecificationName;
                                outEntity.SpecificationServiceConfigId = specificServiceDto.SpecificationServiceConfigId;
                                outEntity.SpecificationServiceName = specificServiceDto.SpecificationServiceName;
                                outEntity.Price = specificServiceDto.Price;
                                outEntities.Add(outEntity);
                            }
                        }
                    }
                }
            }
            moveSpecificServiceCost.CostValue = specificServiceAmount;
            #endregion
            #endregion

            #region 运输特殊服务费
            OrderCostChecklistDto transportSpecificServiceCost = new OrderCostChecklistDto();
            transportSpecificServiceCost.CostCode = OrderCostType.TransportSpecificServiceAmount.ToString();
            transportSpecificServiceCost.CostTitle = OrderCostType.TransportSpecificServiceAmount.GetDescriptionString(); //运输特殊服务费
            transportSpecificServiceCost.Checklist = new List<OrderCostChecklistDto>();
            decimal transportSpecificServiceAmount = 0;
            int transportSpecificServiceCount = requestDto.BigGoodsCount.HasValue && requestDto.BigGoodsCount.Value > 0 ? requestDto.BigGoodsCount.Value : 1;
            #region 计算运输特殊服务费
            outSpecificEntities = new List<OrderSpecificServiceRecordEntity>();
            if (requestDto.SpecificService != null && requestDto.SpecificService.Any())
            {
                foreach (var specificService in requestDto.SpecificService)
                {
                    if (specificService.TransportSpecificServiceConfigOverwriteId.HasValue && specificService.TransportSpecificServiceConfigOverwriteId.Value > 0)
                    {
                        var specificServiceDto = this.transportSpecificServiceConfigOverWriteService.GetById(specificService.TransportSpecificServiceConfigOverwriteId.Value);
                        if (specificServiceDto != null)
                        {
                            decimal servicePrice = specificServiceDto.ServiceAmount * transportSpecificServiceCount;
                            transportSpecificServiceAmount += servicePrice;
                            OrderCostChecklistDto specificServiceCostItem = new OrderCostChecklistDto();
                            specificServiceCostItem.CostCode = OrderCostType.TransportSpecificServiceChildAmount.ToString();
                            specificServiceCostItem.CostTitle = specificServiceDto.ServiceTitle;
                            specificServiceCostItem.CostValue = servicePrice;
                            specificServiceCostItem.ParentCostCode = transportSpecificServiceCost.CostCode;
                            transportSpecificServiceCost.Checklist.Add(specificServiceCostItem);
                            if (createOrder)
                            {
                                OrderSpecificServiceRecordEntity outEntity = new OrderSpecificServiceRecordEntity();
                                outEntity.TransportSpecificServiceConfigId = specificService.TransportSpecificServiceConfigId;
                                outEntity.ServiceTitle = specificServiceDto.ServiceTitle;
                                outEntity.SpecificServiceType = specificServiceDto.SpecificServiceType;
                                outEntity.HasRemark = specificServiceDto.HasRemark;
                                outEntity.ServiceRemark = specificServiceDto.ServiceRemark;
                                outEntity.ServiceAmount = specificServiceDto.ServiceAmount;
                                outEntity.HasUnit = specificServiceDto.HasUnit;
                                outEntity.ServiceUnit = specificServiceDto.ServiceUnit;
                                outSpecificEntities.Add(outEntity);
                            }
                        }
                    }
                    else
                    {
                        var specificServiceDto = this.transportSpecificServiceConfigService.GetById(specificService.TransportSpecificServiceConfigId);
                        if (specificServiceDto != null)
                        {
                            decimal servicePrice = specificServiceDto.ServiceAmount * transportSpecificServiceCount;
                            transportSpecificServiceAmount += servicePrice;
                            OrderCostChecklistDto specificServiceCostItem = new OrderCostChecklistDto();
                            specificServiceCostItem.CostCode = OrderCostType.TransportSpecificServiceChildAmount.ToString();
                            specificServiceCostItem.CostTitle = specificServiceDto.ServiceTitle;
                            specificServiceCostItem.CostValue = servicePrice;
                            specificServiceCostItem.ParentCostCode = transportSpecificServiceCost.CostCode;
                            transportSpecificServiceCost.Checklist.Add(specificServiceCostItem);
                            if (createOrder)
                            {
                                OrderSpecificServiceRecordEntity outEntity = new OrderSpecificServiceRecordEntity();
                                outEntity.TransportSpecificServiceConfigId = specificService.TransportSpecificServiceConfigId;
                                outEntity.ServiceTitle = specificServiceDto.ServiceTitle;
                                outEntity.SpecificServiceType = specificServiceDto.SpecificServiceType;
                                outEntity.HasRemark = specificServiceDto.HasRemark;
                                outEntity.ServiceRemark = specificServiceDto.ServiceRemark;
                                outEntity.ServiceAmount = specificServiceDto.ServiceAmount;
                                outEntity.HasUnit = specificServiceDto.HasUnit;
                                outEntity.ServiceUnit = specificServiceDto.ServiceUnit;
                                outSpecificEntities.Add(outEntity);
                            }
                        }
                    }
                }
            }
            transportSpecificServiceCost.CostValue = transportSpecificServiceAmount;
            #endregion
            #endregion


            #region 优惠券
            OrderCostChecklistDto couponServiceCost = new OrderCostChecklistDto();
            couponServiceCost.CostCode = OrderCostType.CouponAmount.ToString();
            couponServiceCost.CostTitle = OrderCostType.CouponAmount.GetDescriptionString(); //优惠券金额
            couponServiceCost.CostValue = 0;
            if (!requestDto.CouponId.HasValue && marketingCouponDto != null)
            {
                couponServiceCost.CostValue = 0 - marketingCouponDto.CouponAmount;
            }
            #endregion

            #region 保价服务
            InsuredConfigDto insuredConfigDto = null;
            OrderCostChecklistDto insuredServiceCost = new OrderCostChecklistDto();
            insuredServiceCost.CostCode = OrderCostType.InsuredServiceAmount.ToString();
            insuredServiceCost.CostTitle = OrderCostType.InsuredServiceAmount.GetDescriptionString(); //保价服务费
            insuredServiceCost.CostValue = 0;

            if (requestDto.IsInsuredPrice)
            {
                insuredConfigDto = this.insuredConfigService.Get(requestDto.InsuredConfigId.Value);
                if (insuredConfigDto == null)
                {
                    throw new ArgumentException("保价信息不正确!");
                }
                insuredServiceCost.CostValue = requestDto.InsuredPrice.Value * insuredConfigDto.InsuredFeeRatio;
            }
            #endregion

            //续程距离
            int surplusDistance = distanceTotal > freightConfiguration.StartMileage ? distanceTotal - freightConfiguration.StartMileage : 0;
            //续程金额
            decimal surplusDistanceAmount = surplusDistance * freightConfiguration.MileagePrice;
            //夜间订单费率定义
            decimal orderExtractProportion = isNight && nightFreightConfigurationDto.OrderExtractProportion > 0 ? 1 + (decimal.Parse(nightFreightConfigurationDto.OrderExtractProportion.ToString()) / 100) : 1;
            //总费用
            decimal total = freightConfiguration.StartPrice + surplusDistanceAmount + suiteConfig.CarryServiceAmount;
            //夜间总费用
            decimal nightTotal = total * orderExtractProportion;

            List<OrderCostChecklistDto> list = new List<OrderCostChecklistDto>();
            OrderCostChecklistDto orderFreightCost = new OrderCostChecklistDto();
            orderFreightCost.CostCode = OrderCostType.FreightTotal.ToString();
            orderFreightCost.CostTitle = OrderCostType.FreightTotal.GetDescriptionString(); //运费合计
            orderFreightCost.CostValue = (isNight ? nightTotal : total) - (suiteConfig.CouponAmount.HasValue ? suiteConfig.CouponAmount.Value : 0);
            orderFreightCost.Checklist = new List<OrderCostChecklistDto>();
            OrderCostChecklistDto orderStartCost = new OrderCostChecklistDto();
            orderStartCost.CostCode = OrderCostType.StartPrice.ToString();
            orderStartCost.CostTitle = OrderCostType.StartPrice.GetDescriptionString(); //起步金额
            orderStartCost.CostValue = isNight ? freightConfiguration.StartPrice * orderExtractProportion : freightConfiguration.StartPrice;
            orderStartCost.ParentCostCode = orderFreightCost.CostCode;
            orderFreightCost.Checklist.Add(orderStartCost);
            if (surplusDistanceAmount > 0)
            {
                OrderCostChecklistDto orderSurplusCost = new OrderCostChecklistDto();
                orderSurplusCost.CostCode = OrderCostType.SurplusDistanceAmount.ToString();
                orderSurplusCost.CostTitle = OrderCostType.SurplusDistanceAmount.GetDescriptionString(); //续程金额
                orderSurplusCost.CostValue = isNight ? surplusDistanceAmount * orderExtractProportion : surplusDistanceAmount;
                orderSurplusCost.ParentCostCode = orderFreightCost.CostCode;
                orderFreightCost.Checklist.Add(orderSurplusCost);
            }
            if (suiteConfig.CarryServiceAmount > 0)
            {
                OrderCostChecklistDto orderServiceCost = new OrderCostChecklistDto();
                orderServiceCost.CostCode = OrderCostType.CarryServiceAmount.ToString();
                orderServiceCost.CostTitle = OrderCostType.CarryServiceAmount.GetDescriptionString(); //搬运费
                orderServiceCost.CostValue = isNight ? suiteConfig.CarryServiceAmount * orderExtractProportion : suiteConfig.CarryServiceAmount;
                orderServiceCost.ParentCostCode = orderFreightCost.CostCode;
                orderFreightCost.Checklist.Add(orderServiceCost);
            }
            if ((suiteConfig.CouponAmount.HasValue ? suiteConfig.CouponAmount.Value : 0) > 0)
            {
                OrderCostChecklistDto orderCouponCost = new OrderCostChecklistDto();
                orderCouponCost.CostCode = OrderCostType.SuiteCouponAmount.ToString();
                orderCouponCost.CostTitle = OrderCostType.SuiteCouponAmount.GetDescriptionString(); //套餐优惠金额
                orderCouponCost.CostValue = 0 - suiteConfig.CouponAmount.Value;
                orderCouponCost.ParentCostCode = orderFreightCost.CostCode;
                orderFreightCost.Checklist.Add(orderCouponCost);
            }

            list.Add(orderFreightCost);
            if (moveSpecificServiceCost.CostValue > 0)
            {
                list.Add(moveSpecificServiceCost);
            }
            if (transportSpecificServiceCost.CostValue > 0)
            {
                list.Add(transportSpecificServiceCost);
            }
            if (couponServiceCost.CostValue > 0)
            {
                list.Add(couponServiceCost);
            }
            if (insuredServiceCost != null)
            {
                list.Add(insuredServiceCost);
            }
            OrderCostChecklistDto orderCostTotal = new OrderCostChecklistDto();
            orderCostTotal.CostCode = OrderCostType.OrderTotal.ToString();
            orderCostTotal.CostTitle = OrderCostType.OrderTotal.GetDescriptionString(); //订单合计
            orderCostTotal.CostValue = orderFreightCost.CostValue + moveSpecificServiceCost.CostValue + transportSpecificServiceCost.CostValue + couponServiceCost.CostValue+ insuredServiceCost.CostValue;
            list.Add(orderCostTotal);
            #region 订单信息预设            
            entity = new OrderEntity();
            if (createOrder)
            {
                var suiteBusinessConfigDto = suiteBusinessConfigList.Single(p => p.SuiteBusinessType == VehicleSuiteBusinessType.WorryFreeMove && p.Enabled && p.CountyCode == requestDto.CountyCode);
                entity.VehicleSuiteBusinessConfigId = suiteBusinessConfigDto.VehicleSuiteBusinessConfigId;
                entity.SuiteBusinessType = suiteBusinessConfigDto.SuiteBusinessType.ToString();
                entity.SuiteBusinessName = suiteBusinessConfigDto.SuiteBusinessName;
                entity.SuiteName = suiteConfig.SuiteName;
                entity.VehicleBusinessMappingId = suiteConfig.VehicleBusinessMappingId;
                entity.VehicleTypeId = suiteConfig.VehicleTypeId;
                entity.VehicleTypeName = suiteConfig.VehicleTypeName;
                entity.VehicleCategory = vehicleBusinessMappingOverwriteDto.VehicleCategory;
                entity.VehicleCategoryName = vehicleBusinessMappingOverwriteDto.VehicleCategoryName;
                string address = requestDto.Address;
                string zoneName = string.Format("{0}{1}{2}", zoneEntity.provinceEntity.ProvinceName, zoneEntity.cityEntity.CityName, zoneEntity.countyEntity.CountyName);
                address = address.Replace(zoneName, "");
                zoneName = string.Format("{0}{1}", zoneEntity.provinceEntity.ProvinceName, zoneEntity.countyEntity.CountyName);
                address = address.Replace(zoneName, "");
                entity.ShippingAddress = address;
                entity.ProvinceCode = zoneEntity.provinceEntity.ProvinceCode;
                entity.ProvinceName = zoneEntity.provinceEntity.ProvinceName;
                entity.CityCode = zoneEntity.cityEntity.CityCode;
                entity.CityName = zoneEntity.cityEntity.CityName;
                entity.CountyCode = zoneEntity.countyEntity.CountyCode;
                entity.CountyName = zoneEntity.countyEntity.CountyName;
                entity.Longitude = requestDto.Longitude;
                entity.Latitude = requestDto.Latitude;
                entity.FreightConfigurationId = freightConfiguration.FreightConfigurationId;
                entity.StartPrice = isNight ? freightConfiguration.StartPrice * orderExtractProportion : freightConfiguration.StartPrice;
                entity.StartMileage = freightConfiguration.StartMileage;
                entity.ContinueMileage = surplusDistance;
                entity.ContinueMileagePrice = freightConfiguration.MileagePrice;
                entity.ContinueMileageAmount = surplusDistanceAmount;
                if (moveSpecificServiceCost.CostValue > 0)
                {
                    entity.MoveHouseSpecificationService = string.Join(",", moveSpecificServiceCost.Checklist.Select(p => p.CostTitle));
                    entity.MoveHouseServiceAmount = moveSpecificServiceCost.CostValue;
                    entity.BigGoodsNumber = specificServiceCount;
                }
                entity.SuiteForCrowdTitle = suiteConfig.SuiteForCrowdTitle;
                entity.SuiteForCrowdRemark = suiteConfig.SuiteForCrowdRemark;
                entity.SuiteServiceTitle = suiteConfig.SuiteServiceTitle;
                entity.SuiteServiceRemark = suiteConfig.SuiteServiceRemark;
                entity.CarryServiceAmount = suiteConfig.CarryServiceAmount;
                entity.SuiteCouponAmount = 0 - suiteConfig.CouponAmount;
                if (isNight)
                {
                    entity.NightFreightOrderExtractProportion = nightFreightConfigurationDto.OrderExtractProportion;
                    entity.NightFreightAdditionalAmount = total * nightFreightConfigurationDto.OrderExtractProportion;
                }
                entity.CouponAmount = couponServiceCost.CostValue;
                entity.OrderAmount = orderCostTotal.CostValue;
                entity.FreightCostAmount = orderFreightCost.CostValue;
                entity.TotalDistanceLength = distanceTotal;

                var agentRecordDto = this.agentRecordService.Get(agentAreaRecordDto.AgentRecordId);
                entity.AgentRecordId = agentRecordDto.AgentRecordId;
                entity.CompanyId = agentRecordDto.CompanyId;
                if (agentRecordDto.AgentLevel == 3)
                {
                    if (agentRecordDto.ParentCompanyId != 1)
                    {
                        var twoAgentRecordDto = this.agentRecordService.GetByCompanyId(agentRecordDto.ParentCompanyId);
                        if (twoAgentRecordDto != null)
                        {
                            entity.TwoAgentRecordId = twoAgentRecordDto.AgentRecordId;
                            if (twoAgentRecordDto.ParentCompanyId != 1)
                            {
                                var oneAgentRecordDto = this.agentRecordService.GetByCompanyId(twoAgentRecordDto.ParentCompanyId);
                                if (oneAgentRecordDto != null)
                                {
                                    entity.OneAgentRecordId = oneAgentRecordDto.AgentRecordId;
                                }
                            }
                        }
                    }
                }
                else if (agentRecordDto.ParentCompanyId != 1)
                {
                    var oneAgentRecordDto = this.agentRecordService.GetByCompanyId(agentRecordDto.ParentCompanyId);
                    if (oneAgentRecordDto != null)
                    {
                        entity.OneAgentRecordId = oneAgentRecordDto.AgentRecordId;
                    }
                }
                if (requestDto.IsInsuredPrice)
                {
                    entity.InsuredConfigId = insuredConfigDto.InsuredConfigId;
                    entity.InsuredPrice = insuredServiceCost.CostValue;
                    entity.InsuredPriceAmount = insuredServiceCost.CostValue;
                    entity.InsuredPriceChargeAmount = insuredServiceCost.CostValue;
                }
                //if (requestDto.IsCod)
                //{
                //    entity.CodCost = requestDto.CodCost;
                //    entity.CodCostAmount = requestDto.CodCost;
                //}
            }
            #endregion
            return list;
        }
        #endregion

        #region 下单
        #region 检查信息
        private void CheckOrderRequestInfo(WorryFreeMoveSuiteOrderRequestDto orderRequestDto)
        {
            string[] imageSuffixes = new string[] { "jpg", "jpeg" };
            #region 必要检查
            if (!orderRequestDto.GoodsAddress.Any())
            {
                throw new ArgumentException("请填写货物及目的地信息及联系信息");
            }
            if (!orderRequestDto.GoodsAddress.Any(p => p.AddressType == AddressType.Place))
            {
                throw new ArgumentException("请填写卸货地址信息及联系信息");
            }
            if (string.IsNullOrWhiteSpace(orderRequestDto.ShippingAddress) || string.IsNullOrWhiteSpace(orderRequestDto.Shipping) || string.IsNullOrWhiteSpace(orderRequestDto.ShippingPhone))
            {
                throw new ArgumentException("请填写装货地址信息及联系信息");
            }
            if (orderRequestDto.GoodsAddress.Any(p => !p.GoodsWeight.HasValue && !p.GoodsVolume.HasValue))
            {
                throw new ArgumentException("请填写货物重量或体积");
            }
            if (!orderRequestDto.VehicleTypeId.HasValue)
            {
                throw new ArgumentException("请选择车型");
            }
            if (!orderRequestDto.VehicleCategoryReferenceId.HasValue)
            {
                throw new ArgumentException("此套餐车辆分类不可为空");
            }

            if (orderRequestDto.GoodsAddress.Any(p => p.AddressType == AddressType.Take && string.IsNullOrWhiteSpace(p.GoodsPhoto)))
            {
                throw new ArgumentException("各装货地货物照片都应填写，不可为空");
            }
            #endregion

            #region 检查额外服务

            if (orderRequestDto.IsInsuredPrice)
            {
                if (!orderRequestDto.InsuredPrice.HasValue)
                {
                    throw new ArgumentException("请输入保价金额");
                }
                /* 
                if (string.IsNullOrWhiteSpace(orderRequestDto.InsuredPriceCertificates))
                {
                    throw new ArgumentException("请上传保价货物价值证明");
                }

                if (!imageSuffixes.Contains(orderRequestDto.InsuredPriceCertificates.Substring(orderRequestDto.InsuredPriceCertificates.LastIndexOf(".") + 1)))
                {
                    throw new ArgumentException("请上传保价货物价值证明");
                }
                */
            }
            if (orderRequestDto.IsCod)
            {
                if (!orderRequestDto.CodCost.HasValue)
                {
                    throw new ArgumentException("请输入代收货款金额");
                }
                /*
                if (string.IsNullOrWhiteSpace(orderRequestDto.CodGoodsValueCertificates))
                {
                    throw new ArgumentException("请上代收货款价值凭证");
                }
                if (!imageSuffixes.Contains(orderRequestDto.CodGoodsValueCertificates.Substring(orderRequestDto.CodGoodsValueCertificates.LastIndexOf(".") + 1)))
                {
                    throw new ArgumentException("请上代收货款价值凭证");
                }
                */
            }
            #endregion 检查额外服务
        }
        #endregion

        
        public OrderDto Create(OrderBaseRequestDto requestDto, long userId, long? transportOrderId)
        {
            WorryFreeMoveSuiteOrderRequestDto dto = (WorryFreeMoveSuiteOrderRequestDto)requestDto;

            this.CheckOrderRequestInfo(dto);

            TransformOrderShippingCostService transformOrderShippingCostService = new TransformOrderShippingCostService();
            OrderShippingCostRequestDto shippingCostRequestDto = transformOrderShippingCostService.GetRequestDto(dto, VehicleSuiteBusinessType.WorryFreeMove, dto.WorryFreeMoveSuiteConfigId.Value);
            shippingCostRequestDto.MoveSpecificationServices = dto.MoveSpecificationServices;
            var shippingCostList = this.GetShippingCost(shippingCostRequestDto, userId, true, out OrderEntity entity, out List<OrderMoveHouseSpecificationServiceRecordEntity> orderMoveHouseSpecificationServiceRecordEntities, out List<OrderSpecificServiceRecordEntity> orderSpecificServiceRecordEntities);

            var orderFreightRecordList = transformOrderShippingCostService.GetOrderFreightRecords(shippingCostList);

            var companyDto = this.companyService.Get(entity.CompanyId.Value);

            TransportOrderRequestDto transportOrderRequestDto = new TransportOrderRequestDto();
            transportOrderRequestDto.TransportOrderNo = RandomCode.GetOrderNo("YSTMSTO", new SnowflakeWorker(int.Parse(configuration["Snowflake:DatacenterId"]), int.Parse(configuration["Snowflake:ServerId"])).NextId());
            transportOrderRequestDto.SourceType = dto.SourceType;
            transportOrderRequestDto.UserId = userId;
            transportOrderRequestDto.IsBook = dto.IsBook;
            transportOrderRequestDto.BookTime = dto.BookTime;
            transportOrderRequestDto.IsSplitOrder = false;
            transportOrderRequestDto.TransportAmount = shippingCostList.Single(p => p.CostCode == OrderCostType.FreightTotal.ToString()).CostValue;
            transportOrderRequestDto.CountyCode = dto.CountyCode;
            transportOrderRequestDto.CountyCode = dto.CountyCode;
            transportOrderRequestDto.Longitude = dto.Longitude;
            transportOrderRequestDto.Latitude = dto.Latitude;

            var endAddressInfo = dto.GoodsAddress.Where(p => p.AddressType == AddressType.Place).Last();
            transportOrderRequestDto.EndCountyCode = endAddressInfo.EndCountyCode;
            transportOrderRequestDto.EndLongitude = endAddressInfo.EndLongitude;
            transportOrderRequestDto.EndLatitude = endAddressInfo.EndLatitude;

            var moveSpecificationServiceList = dto.MoveSpecificationServices;
            var orderExtentionList = dto.GoodsAddress.Where(p => p.AddressType == AddressType.Place).OrderBy(p => p.EndIndex);


            var shippingGoodsInfo = dto.GoodsAddress.Where(p => p.AddressType == AddressType.Take).OrderBy(p=>p.EndIndex).First();

            List<OrderExtentionEntity> orderExtentionEntities = new List<OrderExtentionEntity>();
            OrderExtentionEntity orderExtentionShippingEntity = new OrderExtentionEntity();
            orderExtentionShippingEntity.Consignee = dto.Shipping;
            orderExtentionShippingEntity.ConsigneePhone = dto.ShippingPhone;
            orderExtentionShippingEntity.EndAddress = entity.ShippingAddress;
            orderExtentionShippingEntity.AddressType = AddressType.Take.ToString();
            orderExtentionShippingEntity.EndProvinceCode = entity.ProvinceCode;
            orderExtentionShippingEntity.EndProvinceName = entity.ProvinceName;
            orderExtentionShippingEntity.EndCityCode = entity.CityCode;
            orderExtentionShippingEntity.EndCityName = entity.CityName;
            orderExtentionShippingEntity.EndCountyCode = entity.CountyCode;
            orderExtentionShippingEntity.EndCountyName = entity.CountyName;
            orderExtentionShippingEntity.EndLongitude = entity.Longitude;
            orderExtentionShippingEntity.EndLatitude = entity.Latitude;
            orderExtentionShippingEntity.GoodsCount = shippingGoodsInfo.GoodsCount;
            orderExtentionShippingEntity.GoodsUnit = shippingGoodsInfo.GoodsUnit;
            orderExtentionShippingEntity.GoodsSku = shippingGoodsInfo.GoodsSku;
            orderExtentionShippingEntity.GoodsName = shippingGoodsInfo.GoodsName;
            orderExtentionShippingEntity.GoodsPhoto = shippingGoodsInfo.GoodsPhoto;
            orderExtentionShippingEntity.GoodsWeight = shippingGoodsInfo.GoodsWeight;
            orderExtentionShippingEntity.GoodsVolume = shippingGoodsInfo.GoodsVolume;
            orderExtentionShippingEntity.GoodsWidth = shippingGoodsInfo.GoodsWidth;
            orderExtentionShippingEntity.GoodsLength = shippingGoodsInfo.GoodsLength;
            orderExtentionShippingEntity.GoodsHeight = shippingGoodsInfo.GoodsHeight;
            orderExtentionShippingEntity.CreateTime = DateTime.Now;
            orderExtentionEntities.Add(orderExtentionShippingEntity);
            foreach (var item in orderExtentionList)
            {
                ZoneEntity zoneEntity = this.zoneService.GetFromZoneEntity(item.EndCountyCode);
                if (zoneEntity == null || zoneEntity.provinceEntity == null || zoneEntity.cityEntity == null || zoneEntity.countyEntity == null)
                {
                    throw new ArgumentException("地址未能匹配到正确的地址信息，请联系客服");
                }
                string address = item.EndAddress;
                string zoneName = string.Format("{0}{1}{2}", zoneEntity.provinceEntity.ProvinceName, zoneEntity.cityEntity.CityName, zoneEntity.countyEntity.CountyName);
                address = address.Replace(zoneName, "");
                zoneName = string.Format("{0}{1}", zoneEntity.provinceEntity.ProvinceName, zoneEntity.countyEntity.CountyName);
                address = address.Replace(zoneName, "");

                OrderExtentionEntity orderExtentionEntity = item.As<OrderExtentionEntity>();
                orderExtentionEntity.Consignee = item.Consignee;
                orderExtentionEntity.ConsigneePhone = item.ConsigneePhone;
                orderExtentionEntity.CreateTime = DateTime.Now;
                orderExtentionEntity.EndIndex = item.EndIndex;
                orderExtentionEntity.EndAddress = address;
                orderExtentionEntity.EndProvinceCode = zoneEntity.provinceEntity.ProvinceCode;
                orderExtentionEntity.EndCityCode = zoneEntity.cityEntity.CityCode;
                orderExtentionEntity.EndCountyCode = zoneEntity.countyEntity.CountyCode;
                orderExtentionEntity.EndProvinceName = zoneEntity.provinceEntity.ProvinceName;
                orderExtentionEntity.EndCityName = zoneEntity.cityEntity.CityName;
                orderExtentionEntity.EndCountyName = zoneEntity.countyEntity.CountyName;
                orderExtentionEntities.Add(orderExtentionEntity);
                if (item.EndIndex.Equals(orderExtentionList.Max(p => p.EndIndex)))
                {
                    entity.EndProvinceCode = zoneEntity.provinceEntity.ProvinceCode;
                    entity.EndCityCode = zoneEntity.cityEntity.CityCode;
                    entity.EndCountyCode = zoneEntity.countyEntity.CountyCode;
                    entity.EndProvinceName = zoneEntity.provinceEntity.ProvinceName;
                    entity.EndCityName = zoneEntity.cityEntity.CityName;
                    entity.EndCountyName = zoneEntity.countyEntity.CountyName;
                    entity.EndLongitude = item.EndLongitude;
                    entity.EndLatitude = item.EndLatitude;
                }
            }

            this.databaseContext.BeginTransaction();

            var transportOrderDto = this.transportOrderService.Add(transportOrderRequestDto);
            #region 订单信息
            entity.CompanyName = companyDto.CompanyName;
            #region 订单基本信息
            entity.OrderNo = RandomCode.GetOrderNo("YSTMSWFMO", new SnowflakeWorker(int.Parse(configuration["Snowflake:DatacenterId"]), int.Parse(configuration["Snowflake:ServerId"])).NextId());
            entity.TransportOrderId = transportOrderDto.TransportOrderId;
            entity.TransportOrderNo = transportOrderDto.TransportOrderNo;
            entity.SourceType = requestDto.SourceType.ToString();
            //TODO:大客户完成后，需要增加大客户价格检查。
            //entity.IsVip = 
            entity.UserId = dto.UserId;
            entity.Shipping = dto.Shipping;
            entity.ShippingPhone = dto.ShippingPhone;
            entity.ShippingAddress = dto.ShippingAddress;
            entity.Consignee = endAddressInfo.Consignee;
            entity.ConsigneeAddress = endAddressInfo.EndAddress;
            entity.ConsigneePhone = endAddressInfo.ConsigneePhone;

            entity.GoodsPhoto = string.Join(",", dto.GoodsAddress.Where(p => p.AddressType == AddressType.Take).Select(p => p.GoodsPhoto));
            entity.GoodsName = string.Join(",", dto.GoodsAddress.Where(p => p.AddressType == AddressType.Take).Distinct().Select(p => p.GoodsName));
            entity.GoodsWeight = endAddressInfo.GoodsWeight;
            entity.GoodsVolume = endAddressInfo.GoodsVolume;
            entity.GoodsLength = endAddressInfo.GoodsLength;
            entity.GoodsWidth = endAddressInfo.GoodsWidth;
            entity.GoodsHeight = endAddressInfo.GoodsHeight;

            entity.PayMode = dto.PayMode;
            entity.IsBook = dto.IsBook;
            entity.BookTime = dto.BookTime;
            #endregion
            #region 订单运输信息及套餐信息
            entity.VehicleTransportBusinessConfigId = dto.VehicleTransportBusinessConfigId;
            entity.TransportBusiness = dto.VehicleTransportBusinessType.ToString();
            entity.TransportBusinessStr = dto.VehicleTransportBusinessType.GetDescriptionString();
            if (dto.WithCarPeopleNumber.HasValue && dto.WithCarPeopleNumber.Value > 0)
            {
                entity.WithCarPeopleNumber = dto.WithCarPeopleNumber;
                entity.WithCarPeoplePhone = dto.WithCarPeoplePhone;
            }
            #endregion

            #region 给司机捎句话及高德配置
            entity.DriverRemark = dto.DriverRemark;
            entity.MapTruckModeId = 0;
            entity.MapTruckTypeId = 0;
            #endregion
            #endregion
            var orderEntity = this.orderData.Add(entity).GetAwaiter().GetResult();
            if (orderEntity == null)
            {
                throw new ArgumentException("下单失败!");
            }
            var orderPoolEntity = entity.As<OrderPoolEntity>();
            orderPoolEntity.OrderId = orderEntity.OrderId;

            var agentRecordDto = this.agentRecordService.Get(entity.AgentRecordId);
            orderPoolEntity.AssignTimeOut = DateTime.Now.AddSeconds(agentRecordDto.ManualAssignWaitTime);
            orderPoolEntity.AssignType = agentRecordDto.EnabledManualAssign ? OrderAssignType.Manual : OrderAssignType.Auto;
            orderPoolEntity.IsAssignReady = entity.PayMode != PayMode.CurrentlyPay;

            var prderPoolResult = this.orderPoolData.Add(orderPoolEntity).GetAwaiter().GetResult();
            if (prderPoolResult == null)
            {
                throw new ArgumentException("下单失败!");
            }
            foreach (var item in orderExtentionEntities)
            {
                item.OrderId = orderEntity.OrderId;
                item.OrderNo = orderEntity.OrderNo;
                item.CreateTime = DateTime.Now;
            }

            if (!this.orderExtentionData.Add(orderExtentionEntities).GetAwaiter().GetResult())
            {
                throw new ArgumentException("下单失败!");
            }

            if (orderMoveHouseSpecificationServiceRecordEntities.Any())
            {
                foreach (var item in orderMoveHouseSpecificationServiceRecordEntities)
                {
                    item.OrderId = orderEntity.OrderId;
                    item.OrderNo = orderEntity.OrderNo;
                    item.CreateTime = DateTime.Now;
                }
                if (!this.orderMoveHouseSpecificationServiceRecordData.Add(orderMoveHouseSpecificationServiceRecordEntities).GetAwaiter().GetResult())
                {
                    throw new ArgumentException("下单失败!");
                }
            }

            if (orderSpecificServiceRecordEntities.Any())
            {
                foreach (var item in orderSpecificServiceRecordEntities)
                {
                    item.OrderId = orderEntity.OrderId;
                    item.OrderNo = orderEntity.OrderNo;
                    item.CreateTime = DateTime.Now;
                }
                if (!this.orderSpecificServiceRecordData.Add(orderSpecificServiceRecordEntities).GetAwaiter().GetResult())
                {
                    throw new ArgumentException("下单失败!");
                }
            }
            foreach (var item in orderFreightRecordList)
            {
                item.OrderId = orderEntity.OrderId;
                item.OrderNo = orderEntity.OrderNo;
                item.IsOrderNewFreight = true;
                item.CreateTime = DateTime.Now;
            }
            if (!this.orderFreightRecordData.Add(orderFreightRecordList).GetAwaiter().GetResult())
            {
                throw new ArgumentException("下单失败!");
            }
            var freightFormulaRecordEntity = orderEntity.As<OrderFreightFormulaRecordEntity>();
            freightFormulaRecordEntity.RecordTimes = 1;
            freightFormulaRecordEntity.CreateTime = DateTime.Now;
            var freightFormulaRecordResult = this.orderFreightFormulaRecordData.Add(freightFormulaRecordEntity).GetAwaiter().GetResult();
            if (freightFormulaRecordResult == null)
            {
                throw new ArgumentException("下单失败!");
            }
            var orderDto = orderEntity.As<OrderDto>();

            this.databaseContext.Commit();
            return orderDto;
        }

        #endregion

        #region 负重
        public OrderFreightAppendRecordDto ChangeWeight(OrderChangeWeightRequestDto orderChangeWeightRequestDto)
        {
            throw new NotImplementedException();
        }
        #endregion
    }
}
